package com.zzb.framework.modules.mail;

import com.zzb.framework.common.BaseResponse;
import com.zzb.framework.common.FrameworkException;
import com.zzb.framework.modules.mail.entity.Mail;
import com.zzb.framework.modules.mail.service.MailService;
import com.zzb.framework.modules.role.vo.SystemUser;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.concurrent.*;
import java.util.function.Function;

/**
 * 发送邮件的公共方法
 * Created by zhangzhenbin on 17-7-17.
 */
@Component
public class SendEmailComponent {
    private static final Logger logger  = LoggerFactory.getLogger(SendEmailComponent.class);
    @Autowired
    private MailService mailService;
    @Autowired
    private SendEmailFirewall sendEmailFirewall;

    private final static ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * 保存邮件并执行回调
     */
    protected void saveMailAndApply(String to, String subject, String msg, Integer sendStatus, Integer sendTime, String bizContent, Integer bizType, Function<Mail, BaseResponse> function) {
        Mail mail = saveMail(to, subject, msg, sendStatus, sendTime, bizContent, bizType);
        if (function != null) {
            BaseResponse functionRet = function.apply(mail);
            if (!functionRet.isSuccess()) {
                logger.error(functionRet.getMsg());
            }
        }
    }

    /**
     * 初始化一个邮件
     */
    protected Mail saveMail(String to, String subject, String msg, Integer sendStatus, Integer sendTime, String bizContent, Integer bizType) {
        Mail mail = new Mail();
        mail.setFromUser(EmailPropertiesContext.getFrom());
        mail.setToUser(to);
        mail.setMessage(msg);
        mail.setSubject(subject);
        mail.setSendStatus(sendStatus);
        mail.setSendTime(sendTime);
        mail.setBizContent(bizContent == null ? "" : bizContent);
        mail.setBizType(bizType == null ? 1 : bizType);
        BaseResponse<Mail> saveMail = mailService.saveMail(mail, SystemUser.root());
        if (!saveMail.isSuccess())
            throw new FrameworkException(saveMail.getMsg());
        return mail;
    }

    /**
     * 发送邮件
     */
    public void send(String tos, String subject, String msg) {
        send(tos, subject, msg, "", 1, null);
    }

    /**
     * 发送邮件,附带业务内容
     */
    public void send(String tos, String subject, String msg, String bizContent, Integer bizType) {
        send(tos, subject, msg, bizContent, bizType, null);
    }

    /**
     * 发送邮件,并调起一个回调
     */
    public void send(String tos, String subject, String msg, Function<Mail, BaseResponse> function) {
        send(tos, subject, msg, "", 1, function);
    }

    /**
     * 发送邮件，附带业务内容，并调起一个回调
     */
    public void send(String tos, String subject, String msg, String bizContent, Integer bizType, Function<Mail, BaseResponse> function) {
        long currentTimeMillis = System.currentTimeMillis();
        //根据逗号分割用户
        String[] toArrays = tos.split(",");
        if (ArrayUtils.isNotEmpty(toArrays)) {
            for (String to : toArrays) {
                try {
                    executorService.submit(() -> {
                        Thread.currentThread().setName("SendMail[to=" + to + "][subject=" + subject + "]");
                        long inThreadCurrentTimeMillis = System.currentTimeMillis();
                        try {
                            blockSend(to, subject, msg);
                            logger.info("发送邮件成功！[from=" + EmailPropertiesContext.getFrom() + "][to=" + to + "][subject=" + subject + "]");
                            saveMailAndApply(to, subject, msg, 1, new Long(System.currentTimeMillis() - inThreadCurrentTimeMillis).intValue(), bizContent, bizType, function);
                        } catch (Exception e) {
                            logger.error("发送邮件失败！[from=" + EmailPropertiesContext.getFrom() + "][to=" + to + "][subject=" + subject + "][e=" + e.getMessage() + "]");
                            saveMailAndApply(to, subject, msg, 0, new Long(System.currentTimeMillis() - inThreadCurrentTimeMillis).intValue(), bizContent, bizType, function);
                        }
                    }).get(30, TimeUnit.SECONDS);
                } catch (InterruptedException | ExecutionException | TimeoutException e) {
                    logger.error("发送邮件超时！[from=" + EmailPropertiesContext.getFrom() + "][to=" + to + "][subject=" + subject + "][e=" + e.getMessage() + "]");
                    saveMailAndApply(to, subject, msg, 0, new Long(System.currentTimeMillis() - currentTimeMillis).intValue(), bizContent, bizType, function);
                }
            }
        }
    }

    protected void blockSend(String to, String subject, String msg) throws Exception {
        Session session = Session.getDefaultInstance(EmailPropertiesContext.getProperties(), EmailPropertiesContext.getMyAuthenricator());
        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(EmailPropertiesContext.getFrom(), EmailPropertiesContext.getPersonalName()));
        mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
        mimeMessage.setSubject(subject);
        mimeMessage.setSentDate(new Date());
        mimeMessage.setText(msg);
        mimeMessage.saveChanges();
        //防火墙过滤邮件
        sendEmailFirewall.filter(to,mimeMessage);
        Transport.send(mimeMessage);
    }
}